home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / By the Book / Mac C Primer V1 CW9 / 68K and PPC Projects (CW9) / 5.1 - WorldClock / WorldClock.c < prev    next >
C/C++ Source or Header  |  1996-05-28  |  11KB  |  546 lines

  1. /********************************************************/
  2. /*                                                        */
  3. /*  WorldClock Code from Chapter Five of                */
  4. /*                                                        */
  5. /*    *** The Macintosh Programming Primer, 2nd Ed. ***    */
  6. /*                                                      */
  7. /*    Copyright 1992, Dave Mark and Cartwright Reed       */
  8. /*                                                        */
  9. /*  This program demonstrates specific Mac programming    */
  10. /*    techniques.                                            */
  11. /*                                                        */    
  12. /********************************************************/
  13.  
  14. /************************************/
  15. /*                                    */
  16. /*    IMPORTANT!!!!!!!!!!!            */
  17. /*                                    */
  18. /*    Be sure to set the current        */
  19. /*    time zone using the                */
  20. /*    Date & Time Control Panel        */
  21. /*    otherwise WorldClock            */
  22. /*    won't know what the current        */
  23. /*    time zone is!!!                    */
  24. /*                                    */
  25. /************************************/
  26.  
  27. #include <Packages.h>
  28. #include <GestaltEqu.h>
  29.  
  30. #define kBaseResID            128
  31. #define kMoveToFront        (WindowPtr)-1L
  32. #define kUseDefaultProc        (void *)-1L
  33. #define kSleep                20L
  34. #define kLeaveWhereItIs        false
  35.  
  36. #define kIncludeSeconds        true
  37. #define kTicksPerSecond        60
  38. #define kSecondsPerHour        3600L
  39.  
  40. #define kAddCheckMark        true
  41. #define kRemoveCheckMark    false
  42.  
  43. #define kPopupControlID        kBaseResID
  44.  
  45. #define kNotANormalMenu        -1
  46.  
  47. #define mApple                kBaseResID
  48. #define iAbout                1
  49.  
  50. #define mFile                kBaseResID+1
  51. #define iQuit                1
  52.  
  53. #define mFont                100
  54.  
  55. #define mStyle                101
  56. #define iPlain                1
  57. #define iBold                2
  58. #define iItalic                3
  59. #define iUnderline            4
  60. #define iOutline            5
  61. #define iShadow                6
  62.  
  63. #define kPlainStyle            0
  64.  
  65. #define kExtraPopupPixels    25
  66.  
  67. #define kClockLeft            12
  68. #define kClockTop            25
  69. #define kClockSize            24
  70.  
  71. #define kCurrentTimeZone    1
  72. #define kNewYorkTimeZone    2
  73. #define kMoscowTimeZone        3
  74. #define kUlanBatorTimeZone    4
  75.  
  76. #define TopLeft( r )        (*(Point *) &(r).top)
  77. #define BottomRight( r )    (*(Point *) &(r).bottom)
  78.  
  79. #define IsHighBitSet( longNum )        ( (longNum >> 23) & 1 )
  80. #define SetHighByte( longNum )        ( longNum |= 0xFF000000 )
  81. #define ClearHighByte( longNum )    ( longNum &= 0x00FFFFFF )
  82.  
  83.  
  84. /*************/
  85. /*  Globals  */
  86. /*************/
  87.  
  88. Boolean         gDone, gHasPopupControl;
  89. short        gLastFont = 1, gCurrentZoneID = kCurrentTimeZone;
  90. Style        gCurrentStyle = kPlainStyle;
  91. Rect        gClockRect;
  92.  
  93.  
  94. /***************/
  95. /*  Functions  */
  96. /***************/
  97.  
  98. void    ToolBoxInit( void );
  99. void    WindowInit( void );
  100. void    MenuBarInit( void );
  101. void    EventLoop( void );
  102. void    DoEvent( EventRecord *eventPtr );
  103. void     HandleNull( EventRecord *eventPtr );
  104. void    HandleMouseDown( EventRecord *eventPtr );
  105. void    SetUpZoomPosition( WindowPtr window, short zoomInOrOut );
  106. void    HandleMenuChoice( long menuChoice );
  107. void    HandleAppleChoice( short item );
  108. void    HandleFileChoice( short item );
  109. void    HandleFontChoice( short item );
  110. void    HandleStyleChoice( short item );
  111. void    DoUpdate( EventRecord *eventPtr );
  112. long    GetZoneOffset( void );
  113.  
  114.  
  115. /**************************** main **********************/
  116.  
  117. void    main( void )
  118. {
  119.     ToolBoxInit();
  120.     WindowInit();
  121.     MenuBarInit();
  122.     
  123.     EventLoop();
  124. }
  125.  
  126.  
  127. /****************** ToolBoxInit *********************/
  128.  
  129. void    ToolBoxInit( void )
  130. {
  131.     InitGraf( &qd.thePort );
  132.     InitFonts();
  133.     InitWindows();
  134.     InitMenus();
  135.     TEInit();
  136.     InitDialogs( 0L );
  137.     InitCursor();
  138. }
  139.  
  140.  
  141. /****************** WindowInit ***********************/
  142.  
  143. void     WindowInit( void )
  144. {
  145.     WindowPtr         window;
  146.  
  147.     window = GetNewWindow( kBaseResID, nil, kMoveToFront );
  148.     
  149.     if ( window == nil )
  150.     {
  151.         SysBeep( 10 );    /*  Couldn't load the WIND resource!!! */
  152.         ExitToShell();
  153.     }
  154.     
  155.     SetPort( window );
  156.     TextSize( kClockSize );
  157.     
  158.     gClockRect = window->portRect;
  159.     
  160.     ShowWindow( window );
  161. }
  162.  
  163.  
  164. /****************** MenuBarInit ***********************/
  165.  
  166. void    MenuBarInit( void )
  167. {
  168.     Handle            menuBar;
  169.     MenuHandle        menu;
  170.     ControlHandle    control;
  171.     OSErr            myErr;
  172.     long            feature;
  173.     
  174.     menuBar = GetNewMBar( kBaseResID );
  175.     SetMenuBar( menuBar );
  176.  
  177.     menu = GetMHandle( mApple );
  178.     AddResMenu( menu, 'DRVR' );
  179.     
  180.     menu = GetMenu( mFont );
  181.     InsertMenu( menu, kNotANormalMenu );
  182.     AddResMenu( menu, 'FONT' );
  183.     
  184.     menu = GetMenu( mStyle );
  185.     InsertMenu( menu, kNotANormalMenu );
  186.     CheckItem( menu, iPlain, true );
  187.     
  188.     DrawMenuBar();
  189.  
  190.     HandleFontChoice( gLastFont );
  191.     
  192.     myErr = Gestalt( gestaltPopupAttr, &feature );
  193.     gHasPopupControl = ((myErr == noErr) && (feature & (1 << gestaltPopupPresent)));
  194.     
  195.     if ( gHasPopupControl )
  196.         control = GetNewControl( kPopupControlID, FrontWindow() );
  197. }
  198.  
  199.  
  200. /****************** EventLoop ***********************/
  201.  
  202. void    EventLoop( void )
  203. {        
  204.     EventRecord        event;
  205.     
  206.     gDone = false;
  207.     
  208.     while ( gDone == false )
  209.     {
  210.         if ( WaitNextEvent( everyEvent, &event, kSleep, nil ) )
  211.             DoEvent( &event );
  212.         else
  213.             HandleNull( &event );
  214.     }
  215. }
  216.  
  217.  
  218. /****************** DoEvent ***********************/
  219.  
  220. void    DoEvent( EventRecord *eventPtr )
  221. {
  222.     char    theChar;
  223.     
  224.     switch ( eventPtr->what )
  225.     {
  226.         case mouseDown: 
  227.             HandleMouseDown( eventPtr );
  228.             break;
  229.         case keyDown:
  230.         case autoKey:
  231.             theChar = eventPtr->message & charCodeMask;
  232.             if ( (eventPtr->modifiers & cmdKey) != 0 ) 
  233.                 HandleMenuChoice( MenuKey( theChar ) );
  234.             break;
  235.         case updateEvt:
  236.             DoUpdate( eventPtr );
  237.             break;
  238.     }
  239. }
  240.  
  241.  
  242. /****************** HandleNull ***********************/
  243.  
  244. void HandleNull( EventRecord *eventPtr )
  245. {
  246.     static long    lastTime = 0;
  247.  
  248.     if ( (eventPtr->when / kTicksPerSecond) > lastTime )
  249.     {
  250.         InvalRect( &gClockRect );
  251.         lastTime = eventPtr->when / kTicksPerSecond;
  252.     }
  253. }
  254.  
  255.  
  256. /****************** HandleMouseDown ***********************/
  257.  
  258. void    HandleMouseDown( EventRecord *eventPtr )
  259. {
  260.     WindowPtr        whichWindow;
  261.     short            thePart;
  262.     long            menuChoice;
  263.     ControlHandle    control;
  264.     short            ignored;
  265.     
  266.     thePart = FindWindow( eventPtr->where, &whichWindow );
  267.     switch ( thePart )
  268.     {
  269.         case inMenuBar:
  270.             menuChoice = MenuSelect( eventPtr->where );
  271.             HandleMenuChoice( menuChoice );
  272.             break;
  273.         case inSysWindow: 
  274.             SystemClick( eventPtr, whichWindow );
  275.             break;
  276.         case inContent:
  277.             SetPort( whichWindow );
  278.             GlobalToLocal( &eventPtr->where );
  279.             
  280.             if ( FindControl( eventPtr->where, whichWindow, &control ) )
  281.             {
  282.                 ignored = TrackControl( control, eventPtr->where, kUseDefaultProc );
  283.                 gCurrentZoneID = GetCtlValue( control );
  284.             }
  285.             break;
  286.         case inDrag: 
  287.             DragWindow( whichWindow, eventPtr->where, &qd.screenBits.bounds );
  288.             break;
  289.         case inZoomIn:
  290.         case inZoomOut:
  291.             if ( TrackBox( whichWindow, eventPtr->where, thePart ) )
  292.             {
  293.                 SetUpZoomPosition( whichWindow, thePart );
  294.                 ZoomWindow( whichWindow, thePart, kLeaveWhereItIs );
  295.             }
  296.             break;
  297.     }
  298. }
  299.  
  300.  
  301. /****************** SetUpZoomPosition ****************/
  302.  
  303. void    SetUpZoomPosition( WindowPtr window, short zoomInOrOut )
  304. {
  305.     WindowPeek        wPeek;
  306.     WStateData        *wStatePtr;
  307.     Rect            windowRect;
  308.     Boolean            isBig;
  309.     short            deltaPixels;
  310.     
  311.     wPeek = (WindowPeek) window;
  312.     wStatePtr = (WStateData *) *(wPeek->dataHandle);
  313.     
  314.     windowRect = window->portRect;
  315.     LocalToGlobal( &TopLeft( windowRect ) );
  316.     LocalToGlobal( &BottomRight( windowRect ) );
  317.     
  318.     wStatePtr->stdState = windowRect;
  319.     wStatePtr->userState = wStatePtr->stdState;
  320.     
  321.     if ( gHasPopupControl )
  322.     {
  323.         isBig = (windowRect.bottom - windowRect.top) >
  324.                 (gClockRect.bottom - gClockRect.top);
  325.         
  326.         if ( isBig )
  327.             deltaPixels = -kExtraPopupPixels;
  328.         else
  329.             deltaPixels = kExtraPopupPixels;
  330.             
  331.         if ( zoomInOrOut == inZoomIn )
  332.             wStatePtr->userState.bottom += deltaPixels;
  333.         else
  334.             wStatePtr->stdState.bottom += deltaPixels;
  335.     }
  336.     else
  337.         SysBeep( 20 );
  338. }
  339.  
  340.  
  341. /****************** HandleMenuChoice ***********************/
  342.  
  343. void    HandleMenuChoice( long menuChoice )
  344. {
  345.     short    menu;
  346.     short    item;
  347.     
  348.     if ( menuChoice != 0 )
  349.     {
  350.         menu = HiWord( menuChoice );
  351.         item = LoWord( menuChoice );
  352.         
  353.         switch ( menu )
  354.         {
  355.             case mApple:
  356.                 HandleAppleChoice( item );
  357.                 break;
  358.             case mFile:
  359.                 HandleFileChoice( item );
  360.                 break;
  361.             case mFont:
  362.                 HandleFontChoice( item );
  363.                 break;
  364.             case mStyle:
  365.                 HandleStyleChoice( item );
  366.                 break;
  367.         }
  368.         HiliteMenu( 0 );
  369.     }
  370. }
  371.  
  372.  
  373. /****************** HandleAppleChoice ***********************/
  374.  
  375. void    HandleAppleChoice( short item )
  376. {
  377.     MenuHandle    appleMenu;
  378.     Str255        accName;
  379.     short        accNumber;
  380.     
  381.     switch ( item )
  382.     {
  383.         case iAbout:    /*  We'll put up an about box next chapter.*/
  384.             SysBeep( 20 );
  385.             break;
  386.         default:
  387.             appleMenu = GetMHandle( mApple );
  388.             GetItem( appleMenu, item, accName );
  389.             accNumber = OpenDeskAcc( accName );
  390.             break;
  391.     }
  392. }
  393.  
  394.  
  395. /****************** HandleFileChoice ***********************/
  396.  
  397. void    HandleFileChoice( short item )
  398. {
  399.     switch ( item )
  400.     {
  401.         case iQuit :
  402.             gDone = true;
  403.             break;
  404.     }
  405. }
  406.  
  407.  
  408. /****************** HandleFontChoice ***********************/
  409.  
  410. void    HandleFontChoice( short item )
  411. {
  412.     short        fontNumber;
  413.     Str255        fontName;
  414.     MenuHandle     menuHandle;
  415.     
  416.     menuHandle = GetMHandle( mFont );
  417.     
  418.     CheckItem( menuHandle, gLastFont, kRemoveCheckMark );
  419.     CheckItem( menuHandle, item, kAddCheckMark );
  420.     
  421.     gLastFont = item;
  422.     
  423.     GetItem( menuHandle, item, fontName );
  424.     GetFNum( fontName, &fontNumber );
  425.     
  426.     TextFont( fontNumber );
  427. }
  428.  
  429.  
  430. /****************** HandleStyleChoice ***********************/
  431.  
  432. void    HandleStyleChoice( short item )
  433. {
  434.     MenuHandle menuHandle;
  435.     
  436.     switch( item )
  437.     {
  438.         case iPlain:
  439.             gCurrentStyle = kPlainStyle;
  440.             break;
  441.         case iBold:
  442.             if ( gCurrentStyle & bold )
  443.                 gCurrentStyle -= bold;
  444.             else
  445.                 gCurrentStyle |= bold;
  446.             break;
  447.         case iItalic:
  448.             if ( gCurrentStyle & italic )
  449.                 gCurrentStyle -= italic;
  450.             else
  451.                 gCurrentStyle |= italic;
  452.             break;
  453.         case iUnderline:
  454.             if ( gCurrentStyle & underline )
  455.                 gCurrentStyle -= underline;
  456.             else
  457.                 gCurrentStyle |= underline;
  458.             break;
  459.         case iOutline:
  460.             if ( gCurrentStyle & outline )
  461.                 gCurrentStyle -= outline;
  462.             else
  463.                 gCurrentStyle |= outline;
  464.             break;
  465.         case iShadow:
  466.             if ( gCurrentStyle & shadow )
  467.                 gCurrentStyle -= shadow;
  468.             else
  469.                 gCurrentStyle |= shadow;
  470.             break;
  471.     }
  472.     
  473.     menuHandle = GetMHandle( mStyle );
  474.     
  475.     CheckItem( menuHandle, iPlain, gCurrentStyle == kPlainStyle );
  476.     CheckItem( menuHandle, iBold, gCurrentStyle & bold );
  477.     CheckItem( menuHandle, iItalic, gCurrentStyle & italic );
  478.     CheckItem( menuHandle, iUnderline, gCurrentStyle & underline );
  479.     CheckItem( menuHandle, iOutline, gCurrentStyle & outline );
  480.     CheckItem( menuHandle, iShadow, gCurrentStyle & shadow );
  481.     
  482.     TextFace( gCurrentStyle );
  483. }
  484.  
  485.  
  486. /****************** DoUpdate ***********************/
  487.  
  488. void    DoUpdate( EventRecord *eventPtr )
  489. {
  490.     WindowPtr        window;
  491.     Str255            timeString;
  492.     unsigned long    curTimeInSecs;
  493.     
  494.     window = (WindowPtr)eventPtr->message;
  495.     
  496.     BeginUpdate( window );
  497.     
  498.     GetDateTime ( &curTimeInSecs );
  499.     curTimeInSecs += GetZoneOffset();
  500.     
  501.     IUTimeString( (long)curTimeInSecs, kIncludeSeconds,
  502.             timeString );
  503.     
  504.     EraseRect( &gClockRect );
  505.     MoveTo( kClockLeft, kClockTop );
  506.     DrawString( timeString );
  507.     
  508.     DrawControls( window );
  509.     
  510.     EndUpdate( window );
  511. }
  512.  
  513.  
  514. /****************** GetZoneOffset ***********************/
  515.  
  516. long GetZoneOffset( void )
  517. {
  518.     MachineLocation    loc;
  519.     long            delta, defaultZoneOffset;
  520.     
  521.     ReadLocation( &loc );
  522. //    defaultZoneOffset = ClearHighByte( loc.gmtFlags.gmtDelta ); // Pre-2.0 Universal Headers
  523.     defaultZoneOffset = ClearHighByte( loc.u.gmtDelta );
  524.     
  525.     if ( IsHighBitSet( defaultZoneOffset ) )
  526.         SetHighByte( defaultZoneOffset );
  527.         
  528.     switch ( gCurrentZoneID )
  529.     {
  530.         case kCurrentTimeZone :
  531.             delta = defaultZoneOffset;
  532.             break;
  533.         case kNewYorkTimeZone :
  534.             delta = -5L * kSecondsPerHour ;
  535.             break;
  536.         case kMoscowTimeZone :
  537.             delta = 3L * kSecondsPerHour;
  538.             break;
  539.         case kUlanBatorTimeZone :
  540.             delta = 8L * kSecondsPerHour;
  541.             break;
  542.     }
  543.     delta -= defaultZoneOffset;
  544.     
  545.     return delta;
  546. }